// Myself.cpp

// Implementacia Myself.h

#include "Player/World/Myself.h"
#include "Common/Support/Debug.h"
//#include <limits.h>

Myself::Myself(World* w) : Player(w)
{
	effort	= 0;
	stamina = 0;
	vwidth	= NORMAL_VIEW;

	bSendTurnNeckTo = false;
	bNeckSynchronization = false;

	dirValid = true;

	lastSeenTime	= -2;
	seeCount		= 0;
}

// Kopirovaci konstruktor
Myself::Myself(const Myself& player) : Player(player)
{
	effort	= player.effort;
	stamina = player.stamina;
	vwidth	= player.vwidth;

	lastSeenPos		= player.lastSeenPos;
	lastSeenTime	= player.lastSeenTime;
}

// Destruktor
Myself::~Myself()
{

}

// Operator priradenia
Myself& Myself::operator =(const Myself& player)
{
	if(&player == this)
		return *this;

	// Zbytocnost?
	Player::operator =(player);

	effort	= player.effort;
	stamina = player.stamina;
	vwidth	= player.vwidth;

	lastSeenPos		= player.lastSeenPos;
	lastSeenTime	= player.lastSeenTime;

	return *this;
}

// Pozera hrac na tento bod?
bool Myself::IsLookingAt(Point point) const
{
	Angle minAng = DegAngle(0);
	Angle maxAng = DegAngle(0);
	
	switch(vwidth)
	{
	case NARROW_VIEW:
		minAng = DegAngle(-world->params->server->visible_angle / 4);
		maxAng = DegAngle(world->params->server->visible_angle / 4);
		break;
	case NORMAL_VIEW:
		minAng = DegAngle(-world->params->server->visible_angle / 2);
		maxAng = DegAngle(world->params->server->visible_angle / 2);
		break;
	case WIDE_VIEW:
		minAng = DegAngle(-world->params->server->visible_angle);
		maxAng = DegAngle(world->params->server->visible_angle);
		break;
	}
	
	Vector diff = point - pos;
	Angle angle = diff.GetAngle() - absDir - neckDir;

	if(minAng <= angle && angle <= maxAng)
		return true;
	else 
		return false;
}

// Vypocita absolutnu poziciu, smer a rychlost z videnych ciar a vlajok
bool Myself::Recalculate(const SENSE_BODY* sb, const VISUAL_INFO* vi)
{
	int i;
	Angle viewDir;

	// Mame aspon nejaku informaciu?
	if(vi->landmarkCnt == 0 && vi->lineCnt == 0) 
		return false;

	// Vypocita smer pohladu za pouzitia ciar
	if(vi->lineCnt == 0)
	{
		// Nevidim ziadne ciary
		viewDir = absDir + neckDir;
	}
	else
	{
		float maxDist = 0;
		
		// Vidim nejake ciary, iterujem cez ne
		for(i = 0; i < vi->lineCnt; i++)
		{
			if(maxDist <= vi->lines[i].dist)
			{
				maxDist = vi->lines[i].dist;
				Angle hlpDir = DegAngle(vi->lines[i].dir);

				switch(vi->lines[i].type)
				{
				case Top:
					if(hlpDir >= DegAngle(0))
						viewDir = -hlpDir;
					else 
						viewDir = DegAngle(-180) - hlpDir;
					break;
				case Bottom:
					if(hlpDir >= DegAngle(0))
						viewDir = DegAngle(180) - hlpDir;
					else 
						viewDir = -hlpDir;
					break;
				case Left:
					if(hlpDir >= DegAngle(0))
						viewDir = DegAngle(-90) - hlpDir;
					else 
						viewDir = DegAngle(90) - hlpDir;
					break;
				case Right:
					if(hlpDir >= DegAngle(0))
						viewDir = DegAngle(90) - hlpDir;
					else 
						viewDir = DegAngle(-90) - hlpDir;
					break;
				default:
					// Toto by sa nemalo stat!
					break;
				}
			}
		}
	}

	int nFlagsIndexes[55];

	int nValidFlagsCount = 0; 

	for(i = 1; i < vi->landmarkCnt; i++)
	{
		if(vi->landmarks[i].distValid)
		{
			nFlagsIndexes[nValidFlagsCount++] = i;
		}
	}

	// Nenasli sa ziadne vlajky
	if(nValidFlagsCount == 0)
		return true;

	// Zotriedim indexy podla vzdialenosti vlajok
	bool bFlagsChange;

	do
	{
		bFlagsChange = false;
		
		for(int i = 1; i < nValidFlagsCount; i++)
		{
			if(vi->landmarks[nFlagsIndexes[i-1]].dist > vi->landmarks[nFlagsIndexes[i]].dist)
			{
				int nTmp = nFlagsIndexes[i-1];
				nFlagsIndexes[i-1] = nFlagsIndexes[i];
				nFlagsIndexes[i] = nTmp;

				bFlagsChange = true;
			}
		}

	} while (bFlagsChange);

	Point tmpPosition;
	float fTmpX = 0; float fTmpY = 0;

	float fAverageCount = 0;

	for(i = 0; i < nValidFlagsCount; i++)
	{
		Point flagPos = world->params->flags[vi->landmarks[nFlagsIndexes[i]].type];
		Vector flagVec = PolarVector(vi->landmarks[nFlagsIndexes[i]].dist, viewDir + DegAngle(vi->landmarks[nFlagsIndexes[i]].dir));
		tmpPosition = flagPos - flagVec;
		
 		float fDistanceMultip = 250.0f - vi->landmarks[nFlagsIndexes[i]].dist;

		fTmpX += (fDistanceMultip * tmpPosition.GetX());
		fTmpY += (fDistanceMultip * tmpPosition.GetY());
		fAverageCount += fDistanceMultip;


 		if(i >= 2)
			break;
	}

	pos = Point(fTmpX / fAverageCount, fTmpY / fAverageCount);

/*	Point newPos = tmpPosition;
	Point oldPos = pos + vel;

	pos.SetX((newPos.GetX() + oldPos.GetX()) / 2);
	pos.SetY((newPos.GetY() + oldPos.GetY()) / 2);
	
/*	// Uz vieme smer pohladu (viewDir). Ktora je najblizsia vlajka?
	int nearestFlag = -1;
	float nearestDist = 0;
	
	for(i = 1; i < vi->landmarkCnt; i++)
	{
		if(vi->landmarks[i].distValid && (vi->landmarks[i].dist < nearestDist || nearestFlag == -1))
		{
			nearestFlag = i;
			nearestDist = vi->landmarks[i].dist;
		}
	}

	// Nasli sa nejake vhodne vlajky?
	if(vi->landmarkCnt == 0 || nearestFlag == -1)
		return true;

	// Zisti, kde sa nachadza vlajka a aky je nas vektor smerom k nej
	Point flagPos = world->params->flags[vi->landmarks[nearestFlag].type];
	Vector flagVec = PolarVector(vi->landmarks[nearestFlag].dist, viewDir + DegAngle(vi->landmarks[nearestFlag].dir));

	// Nastav moju poziciu od pozicie vlajky a vektora
	pos = flagPos - flagVec;
*/
	// Nastav moj absolutny smer odcitanim smeru mojej hlavy
	absDir = viewDir - neckDir;
	
	// Nastav moju rychlost
	vel = PolarVector(sb->speedSize, viewDir + DegAngle(sb->speedDirection));

	// Ostatne
	dirValid = true;
	
	return true;
}

// Predpoveda svoj stav v nasledujucom kroku
void Myself::Step()
{
	pos = pos + vel;
	vel *= type->player_decay;
}

